<template>
  <div class="upgrade-config">
    <a-form layout="vertical">
      <a-card title="系统信息" :bordered="false">
        <a-descriptions>
          <a-descriptions-item label="当前版本">
            {{ systemInfo.version }}
          </a-descriptions-item>
          <a-descriptions-item label="设备型号">
            {{ systemInfo.model }}
          </a-descriptions-item>
          <a-descriptions-item label="序列号">
            {{ systemInfo.serialNumber }}
          </a-descriptions-item>
        </a-descriptions>
      </a-card>

      <a-card title="手动升级" :bordered="false" style="margin-top: 16px">
        <a-upload v-model:file-list="fileList" :before-upload="beforeUpload" :customRequest="customUpload"
          :accept="'.bin'" :maxCount="1">
          <a-button>
            <upload-outlined></upload-outlined>
            选择固件文件
          </a-button>
          <template #tip>
            <div style="color: #999999; margin-top: 8px">
              仅支持.bin格式的固件文件
            </div>
          </template>
        </a-upload>

        <div v-if="uploadProgress > 0" style="margin-top: 16px">
          <a-progress :percent="uploadProgress" />
        </div>
      </a-card>
    </a-form>

    <a-modal v-model:visible="upgradeModalVisible" title="系统升级" :closable="false" :maskClosable="false"
      :keyboard="false" :footer="null">
      <div class="upgrade-progress">
        <a-progress :percent="upgradeProgress" :status="upgradeStatus" type="circle" />
        <div class="upgrade-message">
          {{ upgradeMessage }}
        </div>
        <a-alert v-if="upgradeStatus === 'success'" message="升级完成，设备正在重启..." type="success" show-icon />
        <a-alert v-if="upgradeStatus === 'exception'" message="升级失败，请重试" type="error" show-icon />
      </div>
    </a-modal>
  </div>
</template>

<script>
import { defineComponent, reactive, ref, computed, onMounted } from 'vue';
import { message } from 'ant-design-vue';
import { UploadOutlined } from '@ant-design/icons-vue';
import request from '../../utils/request';
import SparkMD5 from 'spark-md5';

// 常量定义
const CHUNK_SIZE = 64 * 1024; // 64KB per chunk
const MAX_FILE_SIZE_MB = 100; // 最大文件大小(MB)

/**
 * 使用 spark-md5 计算文件的 MD5值
 * @param {File} file - 需要计算MD5的文件对象
 * @returns {Promise<string>} - 返回MD5哈希值
 */
async function calculateMD5(file) {
  return new Promise((resolve, reject) => {
    const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
    const chunks = Math.ceil(file.size / CHUNK_SIZE);
    let currentChunk = 0;
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();

    fileReader.onload = function (e) {
      spark.append(e.target.result);
      currentChunk++;

      if (currentChunk < chunks) {
        loadNext();
      } else {
        const md5 = spark.end();
        resolve(md5);
      }
    };

    fileReader.onerror = function (e) {
      reject(e);
    };

    function loadNext() {
      const start = currentChunk * CHUNK_SIZE;
      const end = Math.min(start + CHUNK_SIZE, file.size);
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    }

    loadNext();
  });
}

/**
 * 将文件块转换为Base64编码
 * @param {Blob} chunk - 文件块
 * @returns {Promise<string>} - 返回Base64编码的字符串
 */
async function chunkToBase64(chunk) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result.split(',')[1]);
    reader.readAsDataURL(chunk);
  });
}

export default defineComponent({
  name: 'UpgradeConfig',
  components: {
    UploadOutlined
  },
  setup() {
    // 系统信息状态
    const systemInfo = reactive({
      version: '',
      model: '',
      serialNumber: ''
    });

    // 文件上传状态
    const fileList = ref([]);
    const uploadProgress = ref(0);

    // 升级状态
    const upgradeState = reactive({
      modalVisible: false,
      progress: 0,
      status: 'active',
      message: '正在升级系统...'
    });

    /**
     * 文件上传前的验证
     * @param {File} file - 待上传的文件
     * @returns {boolean} - 是否允许上传
     */
     const beforeUpload = (file) => {
      const isValidType = file.name.endsWith('.bin');
      if (!isValidType) {
        message.error('请上传.bin格式的固件文件');
        return false;
      }

      const isLt100M = file.size / 1024 / 1024 < MAX_FILE_SIZE_MB;
      if (!isLt100M) {
        message.error(`固件文件大小不能超过${MAX_FILE_SIZE_MB}MB`);
        return false;
      }

      return true;
    };

    /**
     * 自定义上传实现
     * @param {Object} options - 上传选项
     */
    const customUpload = async ({ file, onProgress, onSuccess, onError }) => {
      try {
        // 计算文件MD5
        const md5 = await calculateMD5(file);

        // 准备文件信息
        const fileInfo = {
          name: file.name,
          size: file.size,
          version: file.name.split('_')[1], // 从文件名解析版本号
          md5: md5
        };

        // 分块上传
        const chunks = Math.ceil(file.size / CHUNK_SIZE);
        let uploadedChunks = 0;

        for (let i = 0; i < chunks; i++) {
          const start = i * CHUNK_SIZE;
          const end = Math.min(start + CHUNK_SIZE, file.size);
          const chunk = file.slice(start, end);

          // 将chunk转换为base64
          const base64Chunk = await chunkToBase64(chunk);

          const data = {
            chunk_index: i,
            total_chunks: chunks,
            chunk_data: base64Chunk,
            file_info: i === 0 ? fileInfo : undefined
          };

          const response = await request.post('/v1/firmware/upload', data);

          if (response.code === 200 && response.data.status === 'success') {
            uploadedChunks++;
            const percent = Math.floor((uploadedChunks / chunks) * 100);
            uploadProgress.value = percent;
            onProgress({ percent });
          } else {
            throw new Error(response.error || response.message || '上传失败');
          }
        }

        onSuccess();
        message.success('固件上传成功');

        // 开始升级流程
        await startUpgradeProcess(fileInfo.version);
      } catch (error) {
        console.error('上传失败:', error);
        onError();
        message.error('固件上传失败：' + (error.message || '未知错误'));
      }
    };

    /**
     * 启动升级流程
     * @param {string} version - 固件版本
     */
    const startUpgradeProcess = async (version) => {
      try {
        const upgradeResponse = await request.post('/v1/firmware/upgrade', {
          version: version,
          force: false
        });

        if (upgradeResponse.code === 200) {
          upgradeState.modalVisible = true;
          upgradeState.progress = 100;
          upgradeState.status = 'success';
          upgradeState.message = '升级指令已下发，设备即将重启...';
        } else {
          throw new Error(upgradeResponse.error?.message || '升级启动失败');
        }
      } catch (error) {
        console.error('启动升级失败:', error);
        message.error('启动升级失败：' + (error.message || '未知错误'));
      }
    };

    // 获取系统信息
    const fetchSystemInfo = async () => {
      try {
        const response = await request.get('/v1/system/info');
        if (response.code === 200) {
          const { firmware_version, model, serial_number } = response.data;
          systemInfo.version = firmware_version;
          systemInfo.model = model;
          systemInfo.serialNumber = serial_number;
        }
      } catch (error) {
        console.error('获取系统信息失败:', error);
        message.error('获取系统信息失败');
      }
    };

    // 组件挂载时获取系统信息
    onMounted(fetchSystemInfo);

    return {
      systemInfo,
      fileList,
      uploadProgress,
      upgradeModalVisible: computed(() => upgradeState.modalVisible),
      upgradeProgress: computed(() => upgradeState.progress),
      upgradeStatus: computed(() => upgradeState.status),
      upgradeMessage: computed(() => upgradeState.message),
      beforeUpload,
      customUpload
    };
  }
});
</script>

<style scoped>
.upgrade-config {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.upgrade-progress {
  text-align: center;
  padding: 24px;
}

.upgrade-message {
  margin-top: 16px;
  font-size: 16px;
}

:deep(.ant-upload-list-item) {
  margin-top: 8px;
}
</style>
